package com.flyco.modules.stm.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.flyco.common.api.vo.Result;
import com.flyco.common.system.vo.LoginUser;
import com.flyco.modules.stm.entity.*;
import com.flyco.modules.stm.mapper.StmRetreatMapper;
import com.flyco.modules.stm.model.RetreatContext;
import com.flyco.modules.stm.service.*;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 业务和出入库关联表
 * @Author: flyco
 * @Date:   2022-11-29
 * @Version: V1.0
 */
@DS("store")
@Service
public class StmRetreatServiceImpl extends ServiceImpl<StmRetreatMapper, StmRetreat> implements IStmRetreatService {
    @Autowired
    private IStmRetreatItemService stmRetreatItemService;
    @Autowired
    private IStmBizInoutRelationService stmBizInoutRelationService;
    @Autowired
    private IStmSkuMaterialService stmSkuMaterialService;
    @Autowired
    private IOaWldbService oaWldbService;
    
    @Transactional
    @Override
    public Result<?> apply(Integer status, List<Long> ids) {
        List<StmRetreat> retreatList = this.list(Wrappers.lambdaQuery(StmRetreat.class).in(StmRetreat::getId, ids));
        List<Long> collect = retreatList.stream().filter(q -> q.getStatus() != 3).map(StmRetreat::getId).collect(Collectors.toList());
        if(!collect.isEmpty()){
            return Result.error("当前发货单状态不允许审批:"+collect);
        }

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if(status!=3){
            ids.forEach(id-> applyOneDeny(id,sysUser.getRealname()));
            return Result.ok("取消成功");
        }else{
            Map<Long, StmRetreat> retreatMap = retreatList.stream().collect(Collectors.toMap(StmRetreat::getId, a->a));
            Map<Long, List<StmRetreatItem>> itemMap = stmRetreatItemService.list(Wrappers.lambdaQuery(StmRetreatItem.class).in(StmRetreatItem::getRetreatId, ids))
                    .stream().collect(Collectors.groupingBy(StmRetreatItem::getRetreatId));
            ids.forEach(id-> applyOnePass(retreatMap.get(id),itemMap.get(id),sysUser.getRealname()));
            return Result.ok("审批成功");
        }
    }

    /**
     * 查询数据，更新单据状态
     */
    @Override
    public Result<RetreatContext> pushOABefore(OaPushDTO oaPushDTO, String userName) {
        //查询要货信息
        StmRetreat stmRetreat = this.getById(oaPushDTO.getId());
        if(stmRetreat==null){
            return Result.fail("查询的信息不存在");
        }
        if(stmRetreat.getStatus()!=1){
            return Result.fail("退仓单状态不正确");
        }
        if(StrUtil.isBlank(stmRetreat.getSapAddressCode())){
            return Result.fail("历史退仓单，请联系管理员维护SAP编码");
        }

        //查询要货单明细
        List<StmRetreatItem> itemList = stmRetreatItemService.list(Wrappers.lambdaQuery(StmRetreatItem.class).eq(StmRetreatItem::getRetreatId, stmRetreat.getId()));

        //查询物料编码。key：productId
        Map<Long,List<StmSkuMaterial>> sapItemCodeMap = stmSkuMaterialService.list(Wrappers.lambdaQuery(StmSkuMaterial.class)
                .in(StmSkuMaterial::getProductId,itemList.stream().map(StmRetreatItem::getProductId).collect(Collectors.toList()))
                .orderByDesc(StmSkuMaterial::getStartTime))
                .stream().collect(Collectors.groupingBy(StmSkuMaterial::getProductId));

        //检查物料编码是否维护
        List<String> collect = itemList.stream().filter(q -> sapItemCodeMap.get(q.getProductId()) == null).map(StmRetreatItem::getProductSn).collect(Collectors.toList());
        if(!collect.isEmpty()){
            return Result.fail("物料编码没有维护："+ collect);
        }

        Date now = new Date();

        //更新退仓单状态1->3
        StmRetreat retreat = new StmRetreat();
        retreat.setStatus(3);
        retreat.setConfirmSales(userName);
        retreat.setConfirmTime(now);
        boolean update = this.update(retreat, Wrappers.lambdaUpdate(StmRetreat.class)
                .eq(StmRetreat::getId, stmRetreat.getId()).eq(StmRetreat::getStatus, 1));
        if(!update){
            return Result.fail("退仓单状态更新失败");
        }

        RetreatContext retreatContext = new RetreatContext();
        retreatContext.setStmRetreat(stmRetreat);
        retreatContext.setItemList(itemList);
        retreatContext.setSapItemCodeMap(sapItemCodeMap);

        return Result.success(retreatContext);
    }

    private void applyOnePass(StmRetreat stmRetreat, List<StmRetreatItem> itemList, String applyName){
        StmRetreat retreat = new StmRetreat();
        retreat.setId(stmRetreat.getId());
        retreat.setStatus(5);
        retreat.setConfirmSales(applyName);
        retreat.setConfirmTime(new Date());
        this.updateById(retreat);

        //创建收货关联表记录
        createStockIn(stmRetreat,applyName);
    }

    /**
     * 要货单收货信息初始化
     */
    private void createStockIn(StmRetreat stmRetreat, String applyName){
        Date date = new Date();
        StmBizInoutRelation stmBizInoutRelation = new StmBizInoutRelation();
        stmBizInoutRelation.setPartnerId(stmRetreat.getPartnerId());
        //出库门店信息
        stmBizInoutRelation.setStoreId(stmRetreat.getStoreId());
        stmBizInoutRelation.setStoreName(stmRetreat.getStoreName());
        //收货门店信息
        stmBizInoutRelation.setSourceStoreId(0L);
        stmBizInoutRelation.setSourceStoreName("总仓");
        stmBizInoutRelation.setStatus(1);
        stmBizInoutRelation.setType("STOCK_OUT");
        stmBizInoutRelation.setStockBizType("STOCK_OUT_TYPE_PURCH_RETURN");
        stmBizInoutRelation.setSourceType("RECEIPT_TYPE_RETREAT");
        stmBizInoutRelation.setSourceId(stmRetreat.getId());
        stmBizInoutRelation.setCreateBy(applyName);
        stmBizInoutRelation.setCreateTime(date);
        boolean inoutSaveResult = stmBizInoutRelationService.save(stmBizInoutRelation);
        if (!inoutSaveResult) {
            throw new RuntimeException("出库记录保存失败,stmReplenishmentId="+stmRetreat.getId());
        }
    }

    /**
     * 取消要货单
     */
    private void applyOneDeny(Long id, String applyName){
        StmRetreat retreat = new StmRetreat();
        retreat.setId(id);
        retreat.setStatus(4);
        retreat.setCancelSales(applyName);
        retreat.setCancelTime(new Date());
        this.updateById(retreat);
    }
}
